package com.titanrise.crm.dao;

import com.titanrise.crm.common.enums.TradeStatusEnum;
import com.titanrise.crm.common.utils.Functions;
import com.titanrise.crm.common.utils.ListPipeUtil;
import com.titanrise.crm.common.utils.Maybe;
import com.titanrise.crm.common.utils.Pair;
import com.titanrise.crm.domain.dto.CustomerDto;
import com.titanrise.crm.domain.dto.MessageDto;
import com.titanrise.crm.domain.dto.TradeDto;
import com.titanrise.crm.domain.model.ClientSalesRelationships;
import com.titanrise.crm.domain.model.Messages;
import com.titanrise.crm.domain.model.Salesperson;
import com.titanrise.crm.domain.model.Trade;
import com.titanrise.crm.environment.annotation.Autowired;
import com.titanrise.crm.environment.annotation.Repository;
import com.titanrise.crm.mapper.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

@Repository
public class SalespersonDao {
    @Autowired
    private com.titanrise.crm.mapper.salespersonMapper salespersonMapper;
    @Autowired
    private TradeMapper tradeMapper;
    @Autowired
    private SysLoginLogMapper logMapper;
    @Autowired
    private MessagesMapper messagesMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private ClientSalesRelationshipsMapper clientSalesRelationshipsMapper;

    public Maybe<Salesperson> findSalespersonByUserID(String userID) {
        Objects.requireNonNull(userID);
        return Maybe.fromNullable(salespersonMapper.selectByUserID(userID));
    }

    public List<Trade> findTradesBySalespersonUidAndStatus(String salespersonID, TradeStatusEnum status) {
        Objects.requireNonNull(salespersonID);
        return Functions.pipe(
                salespersonID,
                tradeMapper::selectBySalespersonId,
                ListPipeUtil.filter(trade -> status == null || trade.getStatus().equals(status.getStatus()))
        );
    }

    public int updateLoginLogLogoutTime(String logId) {
        Objects.requireNonNull(logId);
        return logMapper.updateLogoutTimeByID(logId, LocalDateTime.now());
    }

    public List<MessageDto> findMessagesByReceiverID(String userId) {
        Objects.requireNonNull(userId);
        return messagesMapper.selectDtoByReceiverId(userId);
    }

    public int updateStatusByTradeID(String tradeID, TradeStatusEnum status) {
        Objects.requireNonNull(tradeID);
        Objects.requireNonNull(status);
        return tradeMapper.updateStatus(status.getStatus());
    }

    public List<TradeDto> findTradeDtoBySalespersonID(String salespersonID) {
        Objects.requireNonNull(salespersonID);
        return tradeMapper.selectDtoBySalespersonIO(salespersonID);
    }

    public int updateMessageById(Messages message) {
        Objects.requireNonNull(message);
        Objects.requireNonNull(message.getMessageId());
        Objects.requireNonNull(message.getSenderId());
        Objects.requireNonNull(message.getReceiverId());
        Objects.requireNonNull(message.getContent());
        return messagesMapper.updateMessageById(message);
    }

    public List<CustomerDto> findBelongedCustomer(String salespersonUid) {
        Objects.requireNonNull(salespersonUid);
        return userMapper.selectBelongedCustomerBySalespersonUid(salespersonUid);
    }

    public List<CustomerDto> findNonBelongingCustomer() {
        return userMapper.selectNonBelongingCustomer();
    }

    public int addRelation(String salespersonUid, String customerUid) {
        Objects.requireNonNull(salespersonUid);
        Objects.requireNonNull(customerUid);
        return clientSalesRelationshipsMapper.insertOne(
                ClientSalesRelationships.builder()
                        .salesId(salespersonUid)
                        .clientId(customerUid)
                        .build()
        );
    }

    public boolean existsUsername(String username) {
        Objects.requireNonNull(username);
        return roleMapper.existsUsername(username);
    }

    public int updateUsernameByRoleId(String roleId, String username) {
        Objects.requireNonNull(roleId);
        Objects.requireNonNull(username);
        return roleMapper.updateUsernameById(roleId, username);
    }

    public int updatePasswordByRoleId(String roleId, String password) {
        Objects.requireNonNull(roleId);
        Objects.requireNonNull(password);
        return roleMapper.updatePasswordById(roleId, password);
    }

    public int updateNameById(String roleId, String name) {
        Objects.requireNonNull(roleId);
        Objects.requireNonNull(name);
        return roleMapper.updateNameById(roleId, name);
    }

    public Pair<Integer, Integer> updatePhoneNumberByUid(String userId, String phoneNumber) {
        Objects.requireNonNull(userId);
        Objects.requireNonNull(phoneNumber);
        return Pair.of(salespersonMapper.updatePhoneNumberByUid(userId, phoneNumber), userMapper.updatePhoneNumberByUid(userId, phoneNumber));
    }

    public int updateEmailById(String roleId, String email) {
        Objects.requireNonNull(roleId);
        Objects.requireNonNull(email);
        return roleMapper.updateEmailById(roleId, email);
    }
}
